﻿using System;
using System.Collections;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace Pay.Core.WeiXin {
	/// <summary>
	/// 签名工具类
	/// <para>Init();</para>
	/// <para>初始化函数，默认给一些参数赋值。</para>
	/// <para>SetKey(key_)设置商户密钥</para>
	/// <para>CreateMd5Sign(signParams);字典生成Md5签名</para>
	/// <para>GenPackage(packageParams);获取package包</para>
	/// <para>CreateSHA1Sign(signParams);创建签名SHA1</para>
	/// <para>ParseXML();输出xml</para>
	/// </summary>
	public class RequestHandler {

		public RequestHandler() {
			Parameters = new Hashtable();
		}


		public RequestHandler(HttpContext httpContext) {
			Parameters = new Hashtable();

			this.HttpContext = httpContext ?? HttpContext.Current;

		}
		/// <summary>
		/// 密钥
		/// </summary>
		private string Key;

		protected HttpContext HttpContext;

		/// <summary>
		/// 请求的参数
		/// </summary>
		protected Hashtable Parameters;

		/// <summary>
		/// 初始化函数
		/// </summary>
		public virtual void Init() {
		}

		internal void SetParameter(string v, object userHostAddress) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 获取密钥
		/// </summary>
		/// <returns></returns>
		public string GetKey() {
			return Key;
		}
		/// <summary>
		/// 设置密钥
		/// </summary>
		/// <param name="key"></param>
		public void SetKey(string key) {
			this.Key = key;
		}

		/// <summary>
		/// 设置参数值
		/// </summary>
		/// <param name="parameter"></param>
		/// <param name="parameterValue"></param>
		public void SetParameter(string parameter, string parameterValue) {
			if (parameter != null && parameter != "") {
				if (Parameters.Contains(parameter)) {
					Parameters.Remove(parameter);
				}

				Parameters.Add(parameter, parameterValue);
			}
		}

		/// <summary>
		/// 当参数不为null或空字符串时，设置参数值
		/// </summary>
		/// <param name="parameter"></param>
		/// <param name="parameterValue"></param>
		public void SetParameterWhenNotNull(string parameter, string parameterValue) {
			if (!string.IsNullOrEmpty(parameterValue)) {
				SetParameter(parameter, parameterValue);
			}
		}

		/// <summary>
		/// 创建sha1签名
		/// </summary>
		/// <returns></returns>
		public string CreateSHA1Sign() {
			StringBuilder sb = new StringBuilder();
			ArrayList akeys = new ArrayList(Parameters.Keys);
			akeys.Sort();

			foreach (string k in akeys) {
				string v = (string)Parameters[k];
				if (null != v && "".CompareTo(v) != 0 && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) {
					if (sb.Length == 0) {
						sb.Append(k + "=" + v);
					} else {
						sb.Append("&" + k + "=" + v);
					}
				}
			}
			string paySign = GetSha1(sb.ToString()).ToLower();

			return paySign;
		}

		/// <summary>
		/// 签名算法
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public string GetSha1(string str) {
			//建立SHA1对象
			SHA1 sha = new SHA1CryptoServiceProvider();
			//将mystr转换成byte[] 
			ASCIIEncoding enc = new ASCIIEncoding();
			byte[] dataToHash = enc.GetBytes(str);
			//Hash运算
			byte[] dataHashed = sha.ComputeHash(dataToHash);
			//将运算结果转换成string
			string hash = BitConverter.ToString(dataHashed).Replace("-", "");
			return hash;
		}

		/// <summary>
		/// 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名
		/// </summary>
		/// <param name="key">参数名</param>
		/// <param name="value">参数值</param>
		/// key和value通常用于填充最后一组参数
		/// <returns></returns>
		public virtual string CreateMd5Sign(string key, string value) {
			StringBuilder sb = new StringBuilder();

			ArrayList akeys = new ArrayList(Parameters.Keys);
			akeys.Sort();

			foreach (string k in akeys) {
				string v = (string)Parameters[k];
				if (null != v && "".CompareTo(v) != 0 && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) {
					sb.Append(k + "=" + v + "&");
				}
			}

			sb.Append(key + "=" + value);
			string sign = Core.SecureHelper.GetMD5(sb.ToString(), GetCharset()).ToUpper();

			return sign;
		}

		/// <summary>
		/// 输出XML
		/// </summary>
		/// <returns></returns>
		public string ParseXML() {
			StringBuilder sb = new StringBuilder();
			sb.Append("<xml>");
			foreach (string k in Parameters.Keys) {
				string v = (string)Parameters[k];
				if (Regex.IsMatch(v, @"^[0-9.]$")) {

					sb.Append("<" + k + ">" + v + "</" + k + ">");
				} else {
					sb.Append("<" + k + "><![CDATA[" + v + "]]></" + k + ">");
				}

			}
			sb.Append("</xml>");
			return sb.ToString();
		}

		public Hashtable GetAllParameters() {
			return this.Parameters;
		}

		protected virtual string GetCharset() {
			if (this.HttpContext == null) {
				return Encoding.UTF8.BodyName;
			}

			return this.HttpContext.Request.ContentEncoding.BodyName;
		}
	}
}
